﻿namespace Sidvall.Data
{
    public sealed class FieldValueItemCollection<TField> : System.Collections.ObjectModel.Collection<FieldValueItem>
    {
        #region Public Members

        #region Add

        public FieldValueItem Add(TField fieldId, object value, DataType dataType)
        {
            return AddFieldValueItem(fieldId.ToString(), value, dataType);
        }
        public FieldValueItem Add(TField fieldId, bool? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Boolean);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, bool value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Boolean, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, byte? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Byte);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, byte value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Byte, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, char? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Char);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, char value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Char, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, System.DateTime? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.DateTime);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, System.DateTime value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.DateTime, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, System.DateTimeOffset? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.DateTimeOffset);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, System.DateTimeOffset value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.DateTimeOffset, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, System.Guid? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Guid);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, System.Guid value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Guid, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, decimal? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Decimal);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, decimal value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Decimal, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, double? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Double);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, double value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Double, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, short? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Int16);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, short value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Int16, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, int? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Int32);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, int value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Int32, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, long? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Int64);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, long value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Int64, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, float? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.Single);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, float value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Single, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, string value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.String, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, System.TimeSpan? value)
        {
            if (value == null)
                return Add(fieldId, null, DataType.TimeSpan);
            return Add(fieldId, value.Value);
        }
        public FieldValueItem Add(TField fieldId, System.TimeSpan value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.TimeSpan, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, byte[] value)
        {
            var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize(value), DataType.Byte, false);
            Add(item);
            return item;
        }
        public FieldValueItem Add(TField fieldId, System.Enum value)
        {
            System.Type enumType, valueType;
            object enumValue;

            if (value == null)
                return null;
            enumType = value.GetType();
            if (!System.Enum.IsDefined(enumType, value))
                return null;
            valueType = System.Enum.GetUnderlyingType(enumType);
            enumValue = System.Enum.Parse(enumType, value.ToString(), true);
            if (valueType == typeof(System.Byte))
            {
                var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize((byte)enumValue), DataType.Byte, false);
                Add(item);
                return item;
            }
            else if (valueType == typeof(System.Int16))
            {
                var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize((short)enumValue), DataType.Int16, false);
                Add(item);
                return item;
            }
            else if (valueType == typeof(System.Int32))
            {
                var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize((int)enumValue), DataType.Int32, false);
                Add(item);
                return item;
            }
            else if (valueType == typeof(System.Int64))
            {
                var item = new FieldValueItem(fieldId.ToString(), Sidvall.Serialization.SerializerManager.Current.Serialize((long)enumValue), DataType.Int64, false);
                Add(item);
                return item;
            }
            return null;
        }

        #endregion
        #region AddFieldValueItem

        public FieldValueItem AddFieldValueItem(string fieldName, object value, DataType dataType)
        {
            var item = new FieldValueItem(fieldName, Sidvall.Serialization.SerializerManager.Current.SerializeObject(value, dataType), dataType, false);
            Add(item);
            return item;
        }

        #endregion
        #region AddFieldValueItemFromObject

        public FieldValueItem AddFieldValueItemFromObject(string propertyName, object item)
        {
            var property = Sidvall.SystemContext.Current.CodeManager.GetProperty(item, propertyName);
            var dataType = Sidvall.Data.DataTypeManager.GetDataType(property.PropertyType);
            var value = Sidvall.SystemContext.Current.CodeManager.GetPropertyValue(item, property);
            return AddFieldValueItem(propertyName, value, dataType);
        }

        #endregion

        #endregion
        #region Constructors

        public FieldValueItemCollection()
        {
        }

        #endregion
    }
}
